#include <mach_apic.h>
#include <io_ports.h>
+#define APIC_TIMER_MODE_ONESHOT (0 << 17)
+#define APIC_TIMER_MODE_PERIODIC (1 << 17)
+#define APIC_TIMER_MODE_TSC_DEADLINE (2 << 17)
+#define APIC_TIMER_MODE_MASK (3 << 17)
+
+static int tdt_enabled __read_mostly;
+static int tdt_enable __initdata = 1;
+boolean_param("tdt", tdt_enable);
+
static struct {
int active;
/* r/w apic fields */
lvtt_value = /*APIC_LVT_TIMER_PERIODIC |*/ LOCAL_TIMER_VECTOR;
if (!APIC_INTEGRATED(ver))
lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
+
+ if ( tdt_enabled )
+ {
+ lvtt_value &= (~APIC_TIMER_MODE_MASK);
+ lvtt_value |= APIC_TIMER_MODE_TSC_DEADLINE;
+ }
+
apic_write_around(APIC_LVTT, lvtt_value);
tmp_value = apic_read(APIC_TDCR);
calibrate_APIC_clock();
+ if ( tdt_enable && boot_cpu_has(X86_FEATURE_TSC_DEADLINE) )
+ {
+ printk(KERN_DEBUG "TSC deadline timer enabled\n");
+ tdt_enabled = 1;
+ }
+
setup_APIC_timer();
local_irq_restore(flags);
if ( !cpu_has_apic )
return 1;
+ if ( tdt_enabled )
+ {
+ wrmsrl(MSR_IA32_TSC_DEADLINE, timeout ? stime2tsc(timeout) : 0);
+ return 1;
+ }
+
if ( timeout && ((expire = timeout - NOW()) > 0) )
apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX);
freq_string(pts->frequency), pts->name);
}
-void cstate_restore_tsc(void)
+u64 stime2tsc(s_time_t stime)
{
struct cpu_time *t;
struct time_scale sys_to_tsc;
s_time_t stime_delta;
- u64 new_tsc;
-
- if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
- return;
t = &this_cpu(cpu_time);
sys_to_tsc = scale_reciprocal(t->tsc_scale);
- stime_delta = read_platform_stime() - t->stime_master_stamp;
+ stime_delta = stime - t->stime_local_stamp;
if ( stime_delta < 0 )
stime_delta = 0;
- new_tsc = t->local_tsc_stamp + scale_delta(stime_delta, &sys_to_tsc);
+ return t->local_tsc_stamp + scale_delta(stime_delta, &sys_to_tsc);
+}
+
+void cstate_restore_tsc(void)
+{
+ if ( boot_cpu_has(X86_FEATURE_NONSTOP_TSC) )
+ return;
- write_tsc(new_tsc);
+ write_tsc(stime2tsc(read_platform_stime()));
}
/***************************************************************************
#define X86_FEATURE_SSE4_2 (4*32+20) /* Streaming SIMD Extensions 4.2 */
#define X86_FEATURE_X2APIC (4*32+21) /* Extended xAPIC */
#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE (4*32+24) /* "tdt" TSC Deadline Timer */
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
#define X86_FEATURE_OSXSAVE (4*32+27) /* OSXSAVE */
#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running under some hypervisor */
#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1<<22)
#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1<<23)
+#define MSR_IA32_TSC_DEADLINE 0x000006E0
+
/* Intel Model 6 */
#define MSR_P6_EVNTSEL0 0x00000186
#define MSR_P6_EVNTSEL1 0x00000187
void cpuid_time_leaf(uint32_t sub_idx, unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx);
+u64 stime2tsc(s_time_t stime);
+
#endif /* __X86_TIME_H__ */
#include <xen/types.h>
#include <public/xen.h>
-#include <asm/time.h>
extern int init_xen_time(void);
extern void cstate_restore_tsc(void);
extern unsigned long cpu_khz;
struct domain;
+struct vcpu;
/*
* System Time
void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds);
+#include <asm/time.h>
+
#endif /* __XEN_TIME_H__ */
/*